package com.whfc.emp.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.exception.BizException;
import com.whfc.common.geometry.Point;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.third.map.MapApi;
import com.whfc.common.third.map.MapLoc;
import com.whfc.common.util.PageUtil;
import com.whfc.emp.dao.*;
import com.whfc.emp.dto.*;
import com.whfc.emp.entity.AppEmp;
import com.whfc.emp.entity.AppFaceGate;
import com.whfc.emp.entity.AppFaceGateConfig;
import com.whfc.emp.entity.AppFaceGatePerson;
import com.whfc.emp.enums.FaceGateType;
import com.whfc.emp.enums.TaskType;
import com.whfc.emp.factory.AppFaceGateServiceFactory;
import com.whfc.emp.manager.AppFaceGateManager;
import com.whfc.emp.manager.FaceGateManager;
import com.whfc.emp.param.*;
import com.whfc.emp.redis.FaceGateRedisDao;
import com.whfc.emp.service.AppFaceGateService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 闸机管理
 *
 * @author hw
 * @version 1.0
 * @date 2021/1/4 10:34
 */
@DubboService(interfaceClass = AppFaceGateService.class, version = "1.0.0", timeout = 30 * 1000)
public class AppFaceGateServiceImpl implements AppFaceGateService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppFaceGateMapper appFaceGateMapper;

    @Autowired
    private AppFaceGateServiceFactory appFaceGateServiceFactory;

    @Autowired
    private AppFaceGatePersonMapper appFaceGatePersonMapper;

    @Autowired
    private AppFaceGateConfigMapper appFaceGateConfigMapper;

    @Autowired
    private AppEmpMapper appEmpMapper;

    @Autowired
    private AppFaceGateRecordMapper appFaceGateRecordMapper;

    @Autowired
    private FaceGateRedisDao faceGateRedisDao;

    @Autowired
    private AppFaceGatePlatformMapper appFaceGatePlatformMapper;

    @Autowired
    private MapApi mapApi;

    @Autowired
    private AppFaceGateManager appFaceGateManager;

    @Override
    public List<AppFaceGateDTO> list(Integer deptId, String keyword) {
        logger.info("获取闸机列表,deptId:{},keyword:{}", deptId, keyword);
        return appFaceGateMapper.selectByDeptId(deptId, keyword);
    }

    @Override
    public void add(AppFaceGateAddParam request) {
        logger.info("添加闸机,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getDeptId(), request.getPlatform());
        faceGateService.add(request);
    }

    @Override
    public void edit(AppFacaGateEditParam request) {
        logger.info("修改闸机,request:{}", request);
        Integer faceGateId = request.getFaceGateId();
        AppFaceGate faceGate = appFaceGateMapper.selectByPrimaryKey(faceGateId);
        if (faceGate == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该闸机不存在");
        }
        faceGate.setName(request.getName());
        faceGate.setDeptId(request.getDeptId());
        faceGate.setDirection(request.getDirection());

        Point point = request.getPoint();
        // 增加闸机位置信息
        if (point != null) {
            Double lng = point.getLng();
            Double lat = point.getLat();
            MapLoc loc = mapApi.geocode(lng, lat);
            faceGate.setLat(lat);
            faceGate.setLng(lng);
            faceGate.setAddress(loc.getAddress());
        }
        appFaceGateMapper.updateByPrimaryKeySelective(faceGate);
        //更新缓存
        AppFaceGateDTO faceGateDTO = new AppFaceGateDTO();
        BeanUtils.copyProperties(faceGate, faceGateDTO);
        faceGateDTO.setFaceGateId(faceGateId);
        faceGateRedisDao.set(faceGate.getDeviceKey(), faceGateDTO);
    }

    @Override
    public void del(Integer faceGateId) {
        logger.info("删除闸机,faceGateId:{}", faceGateId);
        AppFaceGate faceGate = appFaceGateMapper.selectByPrimaryKey(faceGateId);
        if (faceGate == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该闸机不存在");
        }
        //删除闸机
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(faceGateId);
        faceGateService.del(faceGateId);
        //删除缓存
        faceGateRedisDao.del(faceGate.getDeviceKey());
    }

    @Override
    public PageData<AppFaceGateEmpDTO> empList(Integer faceGateId, String keyword, Integer groupId, Integer type, Integer workTypeId, Integer pageNum, Integer pageSize) {
        logger.info("查看闸机授权人员,faceGateId:{},keyword:{},groupId:{}，type：{},workTypeId:{},pageNum:{},pageSize:{}", faceGateId, keyword, groupId, type, workTypeId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AppFaceGateEmpDTO> list = appFaceGatePersonMapper.selectByFaceGateId(faceGateId, keyword, groupId, workTypeId, type);
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public PageData<AppFaceGateEmpDTO> failEmpList(Integer faceGateId, String keyword, Integer groupId, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("查看闸机授权失败人员,faceGateId:{},keyword:{},workTypeId:{},pageNum:{},pageSize:{}", faceGateId, keyword, groupId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AppFaceGateEmpDTO> list = appFaceGatePersonMapper.selectByFailFaceGateId(faceGateId, keyword, groupId);
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public PageData<AppFaceGateEmpDTO> unGrantEmpList(Integer deptId, Integer faceGateId, Integer groupId, String keyword, Integer pageNum, Integer pageSize) {
        logger.info("获取未授权的人员,faceGateId:{},keyword:{},groupId:{},deptId:{},pageNum:{},pageSize:{}", faceGateId, keyword, groupId, deptId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AppFaceGateEmpDTO> list = appFaceGatePersonMapper.selectUnGrantEmp(deptId, faceGateId, groupId, keyword);
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void faceGateGrantEmp(AppFaceGateGrantEmpParam request) {
        logger.info("闸机-添加人员授权,request:{}", request);

        Integer faceGateId = request.getFaceGateId();
        //验证闸机信息
        AppFaceGate faceGate = appFaceGateMapper.selectByPrimaryKey(faceGateId);
        if (faceGate == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该闸机不存在");
        }
        FaceGateType faceGateType = FaceGateType.parseCode(faceGate.getPlatform());

        if (faceGateType == null || !faceGateType.isOnline()) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该闸机无法进行人员授权");
        }
        String deviceKey = faceGate.getDeviceKey();
        request.setDeviceKey(deviceKey);
        // 是否支持批量同步处理
        if (faceGateType.isSupportBatch()) {
            // 批量同步
            CompletableFuture.runAsync(() -> this.faceGateBatchGrantEmpAuth(request));
            return;
        }

        //添加人员授权
        List<Integer> empIdList = request.getEmpIdList();
        StringBuilder message = new StringBuilder();
        for (Integer empId : empIdList) {
            AppEmp appPerson = appEmpMapper.selectByPrimaryKey(empId);
            String empName = appPerson == null ? "" : appPerson.getEmpName();
            //验证照片
            if (appPerson == null || StringUtils.isBlank(appPerson.getAvatar())) {
                message.append(empName).append("请您先上传人员头像，再进行闸机授权");
                logger.info("empId:{}>>>>>该人员不存在或者无图像,不能授权闸机", empId);
                continue;
            }
            //验证是否重复授权
            AppFaceGatePerson faceGatePerson = appFaceGatePersonMapper.selectByFaceGateIdAndEmpId(faceGateId, empId);
            if (faceGatePerson != null) {
                Integer taskType = faceGatePerson.getTaskType();
                //未开始 or 执行中
                if (TaskType.EMP_ADD.getValue().equals(taskType) || TaskType.EMP_IMG_ADD.getValue().equals(taskType) || TaskType.EMP_AUTH.getValue().equals(taskType)) {
                    message.append(empName).append("该人员正在授权");
                    logger.info("empId:{}>>>>>该人员正在执行定时任务", empId);
                    continue;
                }
                //执行失败,初始化-重新执行
                else {
                    faceGatePerson.setTaskType(TaskType.NOT_START.getValue());
                    faceGatePerson.setDeptId(appPerson.getDeptId());
                    appFaceGatePersonMapper.updateByPrimaryKeySelective(faceGatePerson);
                }
            } else {
                faceGatePerson = new AppFaceGatePerson();
                faceGatePerson.setDeptId(appPerson.getDeptId());
                faceGatePerson.setDeviceKey(deviceKey);
                faceGatePerson.setFaceGateId(faceGateId);
                faceGatePerson.setEmpId(empId);
                faceGatePerson.setTaskType(TaskType.NOT_START.getValue());
                appFaceGatePersonMapper.insertSelective(faceGatePerson);
            }

            Integer personId = faceGatePerson.getId();

            CompletableFuture.supplyAsync(() -> {
                FaceGateGrantEmdAddParam param = new FaceGateGrantEmdAddParam();
                param.setDeviceKey(deviceKey);
                param.setEmpId(empId);
                param.setPersonId(personId);
                return faceGateGrantEmdAdd(param);
            }).thenApply(personGuid -> {
                if (StringUtils.isNotBlank(personGuid)) {
                    FaceGateGrantEmdImgAddParam param = new FaceGateGrantEmdImgAddParam();
                    param.setImgUrl(appPerson.getAvatar());
                    param.setPersonGuid(personGuid);
                    param.setPersonId(personId);
                    param.setDeviceKey(deviceKey);
                    return faceGateGrantEmdImgAdd(param);
                }
                return null;
            }).thenAccept(personGuid -> {
                if (StringUtils.isNotBlank(personGuid)) {
                    FaceGateGrantEmdAuthParam param = new FaceGateGrantEmdAuthParam();
                    param.setPersonId(personId);
                    param.setPersonGuid(personGuid);
                    param.setDeviceKey(deviceKey);
                    faceGateGrantEmdAuth(param);
                }
            });

        }
        if (message.length() > 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), message.toString());
        }
    }

    @Override
    public void faceGateBatchGrantEmpAuth(AppFaceGateGrantEmpParam request) throws BizException {
        logger.info("闸机人员批量授权,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getDeviceKey());
        faceGateService.faceGateBatchGrantEmpAuth(request);
    }

    @Override
    public String faceGateGrantEmdAdd(FaceGateGrantEmdAddParam request) {
        logger.info("闸机人员注册,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getDeviceKey());
        return faceGateService.faceGateGrantEmdAdd(request);
    }

    @Override
    public String faceGateGrantEmdImgAdd(FaceGateGrantEmdImgAddParam request) {
        logger.info("闸机人员照片注册,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getDeviceKey());
        return faceGateService.faceGateGrantEmdImgAdd(request);
    }

    @Override
    public String faceGateGrantEmdAuth(FaceGateGrantEmdAuthParam request) {
        logger.info("闸机人员授权,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getDeviceKey());
        return faceGateService.faceGateGrantEmdAuth(request);
    }


    @Override
    public void faceGateRevokeEmp(AppFaceGateGrantEmpParam request) {
        logger.info("闸机-取消人员授权,request:{}", request);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(request.getFaceGateId());
        faceGateService.faceGateRevokeEmp(request);
    }

    @Override
    public String deviceAuthorizationCancel(String deviceKey, String personGuid) {
        logger.info("闸机取消人员授权,deviceKey:{},personGuid：{}", deviceKey, personGuid);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(deviceKey);
        return faceGateService.deviceAuthorizationCancel(deviceKey, personGuid);
    }

    @Override
    public void sync(Integer faceGateId) {
        logger.info("同步闸机授权人员,faceGateId：{}", faceGateId);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(faceGateId);
        faceGateService.sync(faceGateId);
    }


    @Override
    public AppFaceGateDTO getByDeviceKey(String deviceKey) {
        return appFaceGateManager.getByDeviceKey(deviceKey);
    }

    @Override
    public List<AppFaceGateConfigDTO> getFaceGateAppList(Integer deptId) {
        logger.info("查询可选闸机平台,deptId:{}", deptId);
        return appFaceGateConfigMapper.selectByDeptId(deptId);
    }

    @Override
    public List<AppFaceGateConfigDTO> getFaceGateAppList() throws BizException {
        logger.info("查询全部闸机平台");
        return appFaceGateConfigMapper.selectAll();
    }

    @Override
    public void openDoor(Integer faceGateId) throws BizException{
        AppFaceGate faceGate = appFaceGateMapper.selectByPrimaryKey(faceGateId);
        if (faceGate == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该闸机不存在");
        }
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateService(faceGateId);
        faceGateService.openDoor(faceGate.getDeviceKey());
    }

    @Override
    public void refreshToken(Integer configId) {
        logger.info("刷新token configId:{}", configId);
        FaceGateManager faceGateService = appFaceGateServiceFactory.getFaceGateServiceById(configId);
        faceGateService.getToken();
    }

    @Override
    public Date getPersonLastShowTime(String deviceKey, String guid) throws BizException {
        logger.info("查找用户最后一次的刷脸时间 deviceKey:{}，guid：{}", deviceKey, guid);
        return appFaceGateRecordMapper.selectLatestShowTime(deviceKey, guid);
    }

    @Override
    public AppFaceGatePersonDTO getByDeviceKeyAndGuid(String deviceKey, String guid) throws BizException {
        logger.info("根据闸机序列号和人员GUID查找 闸机人员信息 deviceKey:{}，guid：{}", deviceKey, guid);
        AppFaceGatePerson faceGatePerson = appFaceGatePersonMapper.selectByPersonGuidAndDeviceKey(guid, deviceKey);
        if (faceGatePerson == null) {
            return null;
        }
        AppFaceGatePersonDTO appFaceGatePersonDTO = new AppFaceGatePersonDTO();
        BeanUtils.copyProperties(faceGatePerson, appFaceGatePersonDTO);
        return appFaceGatePersonDTO;
    }

    @Override
    public List<AppFaceGateConfigDTO> getFaceGateList(Integer deptId) {
        return appFaceGateConfigMapper.selectDetailListByDeptId(deptId);
    }

    @Override
    public void setFaceGateApp(Integer deptId, List<AppFaceGateConfigDTO> list) {
        //删除旧数据
        appFaceGateConfigMapper.loginDelByDeptId(deptId);
        //保存新数据
        for (AppFaceGateConfigDTO faceGateConfigDTO : list) {
            AppFaceGateConfig faceGateConfig = new AppFaceGateConfig();
            faceGateConfig.setPlatform(faceGateConfigDTO.getPlatform());
            faceGateConfig.setDeptId(deptId);
            faceGateConfig.setAppId(faceGateConfigDTO.getAppId());
            faceGateConfig.setAppKey(faceGateConfigDTO.getAppKey());
            faceGateConfig.setAppSecret(faceGateConfigDTO.getAppSecret());
            faceGateConfig.setRemark(faceGateConfigDTO.getRemark());
            appFaceGateConfigMapper.insertSelective(faceGateConfig);
        }
    }


    @Override
    public List<AppFaceGatePlatformDTO> getAllFaceGatePlatform() {
        return appFaceGatePlatformMapper.selectAll();
    }

}
